package holdem;

import java.io.Serializable;

/**
 *
 * @author Pai Qi
 * @author qipai0@gmail.com
 * Description: The card class
 *
 */

public class Card extends NestedIntegerList implements Serializable, Comparable<Card> {
    private Suite   suite;
    private Integer value;

    public int compareTo(Card o) {

        return value.compareTo(o.value);
    }

    public static enum Suite {
	dimond, heart, spade, club
    }

    //~--- constructors -------------------------------------------------------

    /**
     * Create a new card given its name
     * @param name A string representation of the card.
     * e.g. "11D" or "JD" is a Jack of Diamond,
     * "AS" or "1S" is a Ace of Spade
     */
    public Card(String name) {
	String v;
	String s;

	name = name.toUpperCase();

	if (name.matches("[AJQK][DHSC]")) {
	    v = name.substring(0, 1);
	    s = name.substring(1, 2);

	} else if (name.matches("[0-9]+[DHSC]")) {
	    v = name.substring(0, name.length()-1);
	    s = name.substring(name.length()-1, name.length());
	} else {
	    throw new RuntimeException("Card name (String) illegal");
	}

	setValue(v);
	setSuite(s);
    }

    /**
     * Create a new card given its suite and value
     * @param suite
     * @param value
     */
    public Card(Suite suite, int value) {
	this.suite = suite;
	this.value = value;
    }

    //~--- methods ------------------------------------------------------------

    /**
     *
     * @param anotherCard
     * @return true iff two cards are identical (same suite and same value)
     */
    @Override
    public boolean equals(Object anotherCard) {
	if (anotherCard instanceof Card) {
	    Card c = (Card) anotherCard;

	    if ((c.getValue() == getValue())
		    && c.getSuite().equals(getSuite())) {
		return true;
	    }
	}

	return false;
    }

    /**
     *
     * @return A string representation of this card
     */
    @Override
    public String toString() {
	String valAsString = "";

	switch (value) {

	 case 1:
	     valAsString = "ace";

	     break;

	 case 11:
	     valAsString = "jack";

	     break;

	 case 12:
	     valAsString = "queen";

	     break;

	 case 13:
	     valAsString = "king";

	     break;

	 default:
	     valAsString = new Integer(value).toString();
	}

	return "["+valAsString+" of "+suite.toString()+"]";
    }

    public boolean sameSuite(Card anotherCard) {
	return getSuite().equals(anotherCard.getSuite());
    }

    public boolean sameValue(Card anotherCard) {
	return getValue() == anotherCard.getValue();
    }

    public Suite getSuite() {
	return suite;
    }

    public int getSuiteInt()
    {
        switch(suite)
        {
            case dimond:
                return 0;
            case heart:
                return 1;
            case spade:
                return 2;
            case club:
                return 3;
            default:
                return -1;
        }
    }



    public Integer getValue() {
	return value;
    }

    private void setSuite(String s) {
	s = s.toUpperCase();

	if (s.equals("D")) {
	    suite = Suite.dimond;
	} else if (s.equals("S")) {
	    suite = Suite.spade;
	} else if (s.equals("H")) {
	    suite = Suite.heart;
	} else if (s.equals("C")) {
	    suite = Suite.club;
	} else {
	    assert false;
	}
    }

    private void setValue(int v) {
	assert ((v >= 1) && (v <= 13)) : "Card value (int) illegal";
	value = v;
    }

    private void setValue(String v) {
	v = v.toUpperCase();

	if (v.equals("A")) {
	    value = 1;
	} else if (v.equals("J")) {
	    value = 11;
	} else if (v.equals("Q")) {
	    value = 12;
	} else if (v.equals("K")) {
	    value = 13;
	} else {
	    setValue(Integer.valueOf(v));
	}
    }

}
